/***************************************************************************
 *   Copyleft 2008-2009 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#include "./vStringTokenizer.h"

namespace Vendetta {
	vStringTokenizer::vStringTokenizer(const vString& str, const vString& delim) {
		if (!str.Length() || !delim.Length()) {
			return;
		}
		mTokenizedString = str;
		mDelimeter = delim;

		vUInt uiCurrPos = 0;

		while (true) {
			if ((uiCurrPos = (vUInt) mTokenizedString.Find(mDelimeter, uiCurrPos)) != vString::MaxPos) {
				uiCurrPos += (vUInt) mDelimeter.Length();

				while (mTokenizedString.Find(mDelimeter, uiCurrPos) == uiCurrPos) {
					mTokenizedString.Erase(uiCurrPos, mDelimeter.Length());
				}
			} else {
				break;
			}
		}

		if (!mTokenizedString.Find(mDelimeter, 0)) {
			mTokenizedString.Erase(0, mDelimeter.Length());
		}

		uiCurrPos = 0;
		if ((uiCurrPos = (vUInt) mTokenizedString.ReverseFind(mDelimeter)) != vString::MaxPos) {
			if (uiCurrPos != (mTokenizedString.Length() - mDelimeter.Length())) {
				return;
			}
			mTokenizedString.Erase(mTokenizedString.Length() - mDelimeter.Length(), mDelimeter.Length());
		}

	}


	vInt vStringTokenizer::CountTokens() {
		vUInt uiPrevPos = 0;
		vInt iNrTokens = 0;

		if (mTokenizedString.Length() > 0) {
			iNrTokens = 0;

			vUInt uiCurrPos = 0;
			while (true) {
				if ((uiCurrPos = (vUInt) mTokenizedString.Find(mDelimeter, uiCurrPos)) != vString::MaxPos) {
					iNrTokens++;
					uiPrevPos = uiCurrPos;
					uiCurrPos += (vUInt) mDelimeter.Length();
				} else {
					break;
				}
			}
			
			return ++iNrTokens;
		} else {
			return 0;
		}
	}


	vBool vStringTokenizer::HasMoreTokens() {
		return (mTokenizedString.Length() > 0);
	}


	vString vStringTokenizer::NextToken() {
		if (!mTokenizedString.Length()) {
			return "";
		}

		vString strTemp = "";
		vUInt uiPos = (vUInt) mTokenizedString.Find(mDelimeter,0);

		if (uiPos != vString::MaxPos) {
			strTemp = mTokenizedString.SubString(0, uiPos);
			mTokenizedString = mTokenizedString.SubString(uiPos + mDelimeter.Length(), 
				mTokenizedString.Length() - uiPos);
		} else {
			strTemp = mTokenizedString.SubString(0, mTokenizedString.Length());
			mTokenizedString = "";
		}

		return strTemp;
	}

	vString vStringTokenizer::NextToken(const vString& delimiter) {
		if (!mTokenizedString.Length()) {
			return "";
		}

		vString strTemp = "";
		vUInt uiPos = (vUInt) mTokenizedString.Find(delimiter, 0);

		if (uiPos != vString::MaxPos) {
			strTemp = mTokenizedString.SubString(0, uiPos);
			mTokenizedString = mTokenizedString.SubString(uiPos + delimiter.Length(), 
				mTokenizedString.Length() - uiPos);
		} else {
			strTemp = mTokenizedString.SubString(0, mTokenizedString.Length());
			mTokenizedString = "";
		}

		return strTemp;
	}


	vString vStringTokenizer::RemainingString() {
		return mTokenizedString;
	}


	vString vStringTokenizer::FilterNextToken(const vString& filterStr) {
		vString strTemp = NextToken();
		vUInt currentPos = 0;

		while ((currentPos = (vUInt) strTemp.Find(filterStr,currentPos)) != vString::MaxPos) {
			strTemp.Erase(currentPos, filterStr.Length());
		}

		return strTemp;
	}

	vString vStringTokenizer::EraseDelimeter(const vString& str, const vString& delim, vUInt stBeg, vUInt stEnd) {
		vUInt uiBeg = stBeg, uiCurrPos = stBeg;
		vUInt uiEnd = stEnd;

		if (delim.IsEmpty() || str.IsEmpty()) {
			return str;
		}
		
		if (!stEnd || (stEnd > (vUInt) str.Length())) {
			uiEnd = (vUInt) str.Length();
		}
		if (uiBeg >= uiEnd) {
			return str;
		}
		
		vString strIn = str;
		while ((uiCurrPos = (vUInt) strIn.Find(delim, 0)) != vString::MaxPos) {
			strIn.Erase(uiCurrPos, delim.Length());
		}

		return strIn;
	}

	vString vStringTokenizer::EraseLeadingCharacters(const vString& str, const vChar& delim) {
		vString strRet = str;
		vUInt uiPos = 0;

		while (uiPos < str.Length() && strRet[uiPos] == delim) {
			uiPos++;
		}
		strRet.Erase(0, uiPos);

		return strRet;
	}

	vString vStringTokenizer::EraseTailingCharacters(const vString& str, const vChar& delim) {
		vString strRet = str;
		vUInt uiPos = str.Length() - 1;

		while (uiPos >= 0 && uiPos < str.Length() && strRet[uiPos] == delim) {
			strRet.Erase(uiPos, str.Length());
			uiPos--;
		}

		return strRet;
	}

	vString vStringTokenizer::EraseLeadingTailingCharacters(const vString& str, const vChar& delim) {
		vString strRet;

		strRet = vStringTokenizer::EraseLeadingCharacters(str, delim);

		return vStringTokenizer::EraseTailingCharacters(strRet, delim);
	}

	vArray<vString> vStringTokenizer::Split(const vString& str, const vString& delims) {
		vArray<vString> ret;
		vUInt uiStart, uiPos;
        uiStart = 0;

        do {
			uiPos = str.FindFirstOf(delims, uiStart);
            if (uiPos == uiStart) {
                uiStart = uiPos + 1;
            } else if (uiPos == vString::MaxPos) {
                ret<<(str.SubString(uiStart));
                break;
            } else {
                ret<<(str.SubString(uiStart, uiPos - uiStart));
                uiStart = uiPos + 1;
            }
			uiStart = str.FindFirstNotOf(delims, uiStart);
        } while (uiPos != vString::MaxPos);

		return ret;
	}

}